package com.alvin.demo.utils;

import com.fazecast.jSerialComm.SerialPort;
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import org.junit.Test;

import java.net.InetAddress;

public class ModBusTcp {
    @Test
    public void test01() {
        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName("192.168.1.88"); // 写网关的地址
            // TCP参数设置ip地址
            // tcpParameters.setHost(InetAddress.getLocalHost());
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口，这里设置是默认端口502
            tcpParameters.setPort(Modbus.TCP_PORT);
//            tcpParameters.setPort(8886); // 网关的通讯端口
            tcpParameters.setConnectionTimeout(300);
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
            int slaveId = 1;//从机地址
            int offset = 97;//寄存器读取开始地址
            int quantity = 1;//读取的寄存器数量
            try {
                if (!master.isConnected()) {
                    master.connect();// 开启连接
                }
                // 读取对应从机的数据，readHoldingRegisters，功能码03
                int[] registerValues = master.readHoldingRegisters(slaveId, offset, quantity);
                // 控制台输出
                for (int value : registerValues) {
                    System.out.println("寄存器 " + offset+ " 数据: " + value);
                    offset ++ ;
                }
//                System.out.println((registerValues[0] + registerValues[1]*65535));
            } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
                e.printStackTrace();
            } finally {
                try {
                    master.disconnect();
                } catch (ModbusIOException e) {
                    e.printStackTrace();
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 写入单个寄存器数据 功能吗 6  采样开启或停止
    @Test
    public void test02() {
        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName("192.168.1.88"); // 写网关的地址
            // TCP参数设置ip地址
            // tcpParameters.setHost(InetAddress.getLocalHost());
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口，这里设置是默认端口502
            tcpParameters.setPort(Modbus.TCP_PORT);
//            tcpParameters.setPort(8886); // 网关的通讯端口
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
            int slaveId = 1;//从机地址
            int offset = 124;//寄存器读取开始地址
            int data = 63;// 写入的数据 采样 1、开启 0、停止
            try {
                if (!master.isConnected()) {
                    master.connect();// 开启连接
                }
                // 写入对应寄存器的数据，writeSingleRegister，功能码 06
                master.writeSingleRegister(slaveId, offset, data);

            } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
                e.printStackTrace();
            } finally {
                try {
                    master.disconnect();
                } catch (ModbusIOException e) {
                    e.printStackTrace();
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Test
    public void test03() {
        try {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址
            InetAddress address = InetAddress.getByName("192.168.1.88"); // 写网关的地址
            // TCP参数设置ip地址
            // tcpParameters.setHost(InetAddress.getLocalHost());
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口，这里设置是默认端口502
            tcpParameters.setPort(Modbus.TCP_PORT);
//            tcpParameters.setPort(8886); // 网关的通讯端口
            // 创建一个主机
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
            int slaveId = 1;//从机地址
            int offset = 112;//寄存器读取开始地址

            int [] datas = new int[2] ;
            datas[0] = 29428 ;
            datas[1] = 92 ;
            try {
                if (!master.isConnected()) {
                    master.connect();// 开启连接
                }
                // 写入多个寄存器数据，writeMultipleRegisters，功能码 10
                master.writeMultipleRegisters(slaveId, offset, datas);

            } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
                e.printStackTrace();
            } finally {
                try {
                    master.disconnect();
                } catch (ModbusIOException e) {
                    e.printStackTrace();
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test04() throws InterruptedException {
        // 设置串口一些参数，除了串口号其他基本固定 COM2就是文章前配置的
        SerialPort serialPort = SerialPort.getCommPort("COM3"); // 串口设备名称
        serialPort.setBaudRate(9600); // 波特率
        serialPort.setNumDataBits(8); // 数据位
        serialPort.setParity(SerialPort.NO_PARITY); // 校验位
        serialPort.setNumStopBits(1); // 停止位

        if (serialPort.openPort()) {

            byte[] requestMessage = ModbusRTURequestBuilder.buildModbusRTURequest(
                    1,
                    3,
                    0,
                    2
            );
            // 读取数据
            serialPort.writeBytes(requestMessage, requestMessage.length);

            Thread.sleep(300); // 等待足够的时间以确保传感器响应

            // 响应数据的长度根据以下公式自行调整
            //  从站地址(1) + 功能码(1) + 数据总长度(1) + 数据 + CRC校验(2)
            // 数据总长度20的原因：读取10个寄存器的数据，会返回*2的字节数
            byte[] responseData = new byte[15];

            // 获取响应
            int bytesRead = serialPort.readBytes(responseData, responseData.length);
            System.out.println(bytesRead);
            // 通过打印可以看到，获取的数据为十进制
            System.out.println(NumberUtils.bytesToHexString(responseData , bytesRead));

            serialPort.closePort();
        } else {
            System.out.println("无法打开串口");
        }
    }
}
